#pragma once

namespace AppliedCryptography
{
	namespace AC = AppliedCryptography;

	enum ClassBits
	{
		Universal	= 0x00,
		Application	= 0x40,
		ContextSpec	= 0x80,
		Private		= 0xC0
	};

	enum ConstructedBit
	{
		Primitive	= 0x00,
		Constructed = 0x20
	};

	enum TypeNumberBits
	{
		EOC					= 0x00,
		Boolean				= 0x01,
		Integer				= 0x02,
		BitString			= 0x03,
		OctetString			= 0x04,
		Null				= 0x05,
		ObjectIdentifier	= 0x06,
		ObjectDescriptor	= 0x07,
		External			= 0x08,
		Real				= 0x09,
		Enumerated			= 0x0A,
		EmbeddedPdv			= 0x0B,
		Utf8string			= 0x0C,
		RelativeOid			= 0x0D,
		Sequence			= 0x10,
		SequenceOf			= 0x10,
		Set					= 0x11,
		SetOf				= 0x11,
		NumericString		= 0x12,
		PrintableString		= 0x13,
		T61String			= 0x14,
		VideotexString		= 0x15,
		IA5String			= 0x16,
		UTCTime				= 0x17,
		GeneralizedTime		= 0x18,
		GraphicString		= 0x19,
		VisibleString		= 0x1A,
		GeneralString		= 0x1B,
		UniversalString		= 0x1C,
		CharacterString		= 0x1D,
		BMPString			= 0x1E,
		Explicit00			= 0x00,
		Explicit03			= 0x03
	};

	/*
	 * Type identifier octet:
	 * +---+---+-----+---+---+---+---+---+
	 * | 8 | 7 |  6  | 5 | 4 | 3 | 2 | 1 |
	 * +---+---+-----+---+---+---+---+---+
	 * | Class | P/C |      Number       |
	 * +-------+---- +-------------------+
	*/
	class ASN1Type
	{
	private:
		ClassBits _classBits;
		ConstructedBit _constucted;
		TypeNumberBits _number;

	private:
		ASN1Type();

	protected:
		ASN1Type(ClassBits classBits, ConstructedBit constucted, TypeNumberBits number);
		//ASN1Type(ASN1Type& other);

	protected:
		virtual byte getClassBit() const;
		virtual byte getConstructed() const;
		virtual byte getNumber() const;

	public:
		virtual byte getTypeBits() const;
	};
}; // namespace AppliedCryptography

/*
ASN SEQUENCE:
    Hex: 6e       5d       c0
   Bin : 01101110 01011101 11
Padding:                    000000
  bit #: 12345678 12345678 12345678

DER:
03 04 06 6e 5d c0
 ^  ^  ^  ^
 |  |  |  |
 |  |  |  data (3 bytes)
 |  |  |
 |  |  padding
 |  |
 |  length
 |
 type
*/